package cn.tedu.sjmall.order.webapi.service.impl;

import cn.tedu.sjmall.commons.exception.ShengJiServiceException;
import cn.tedu.sjmall.commons.pojo.domain.SjmallAuthenticationInfo;
import cn.tedu.sjmall.commons.restful.JsonPage;
import cn.tedu.sjmall.commons.restful.ResponseCode;
import cn.tedu.sjmall.order.webapi.mapper.OmsCartMapper;
import cn.tedu.sjmall.order.service.IOmsCartService;
import cn.tedu.sjmall.pojo.order.dto.CartAddDTO;
import cn.tedu.sjmall.pojo.order.dto.CartUpdateDTO;
import cn.tedu.sjmall.pojo.order.model.OmsCart;
import cn.tedu.sjmall.pojo.order.vo.CartStandardVO;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
@Slf4j
public class OmsCartServiceImpl implements IOmsCartService {

    @Autowired
    private OmsCartMapper omsCartMapper;

    // 新增用户选中的sku信息到购物车
    @Override
    public void addCart(CartAddDTO cartDTO) {
        // 实现新增购物车商品信息功能,需要先判断当前用户是否已经将这个sku添加到购物车中了
        // 方法参数中没有用户id信息,所以要从SpringSecurity上下文中获取
        Long userId=getUserId();
        // 根据userId和cartDTO中的skuId来判断用户购物车中是否已经包含
        OmsCart omsCart=omsCartMapper
                .selectExistsCart(userId,cartDTO.getSkuId());
        // 判断omsCart是不是null
        if(omsCart == null){
            // 如果omsCart是null,证明用户要添加的商品不在购物车中
            // 执行新增操作:将cartDTO同名属性赋值到omsCart中
            //            再额外为omsCart对象的userId赋值
            omsCart=new OmsCart();
            BeanUtils.copyProperties(cartDTO,omsCart);
            // 单独为userId赋值
            omsCart.setUserId(userId);
            // 执行新增
            omsCartMapper.saveCart(omsCart);
        }else{
            // 如果omsCart不是null,证明这个sku信息已经存在于当前用户的购物车中了
            // 我们需要做的就是将本次新增到购物车的数量和原有的数量相加后修改数据库
            // 本次新增的数量是cartDTO的quantity属性,原有数量是omsCart的quantity属性
            omsCart.setQuantity(cartDTO.getQuantity()+omsCart.getQuantity());
            // 下将新变化的数量,保存到数据库
            omsCartMapper.updateQuantityById(omsCart);
        }
    }

    @Override
    public JsonPage<CartStandardVO> listCarts(Integer page, Integer pageSize) {
        // 先从SpringSecurity上下文中获取用户id
        Long userId=getUserId();
        // 先设置分页条件,再执行分页查询
        PageHelper.startPage(page,pageSize);
        List<CartStandardVO> list= omsCartMapper.selectCartByUserId(userId);
        // 上面的sql会自动添加limit关键字实现分页查询,下面返回要转换为JsonPage类型
        return JsonPage.restPage(new PageInfo<>(list));
    }

    @Override
    public void removeCart(Long[] ids) {
        // 直接调用删除方法,将ids传入mapper方法参数中
        int rows=omsCartMapper.deleteCartsByIds(ids);
        if(rows == 0){
            throw new ShengJiServiceException(
                    ResponseCode.NOT_FOUND,"您要删除的商品已经在早些时间被删除了!");
        }
    }

    // 清空购物车
    @Override
    public void removeAllCarts() {
        Long userId=getUserId();
        int rows=omsCartMapper.deleteCartsByUserId(userId);
        if (rows == 0){
            throw new ShengJiServiceException(
                    ResponseCode.NOT_FOUND,"您的购物车已经没有任何商品了!");
        }
    }

    // 根据userId和skuId删除购物车商品的方法
    @Override
    public void removeUserCarts(OmsCart omsCart) {
        // 购物车删除效果无需校验,因为生成订单的过程中,
        // 用户的购物车中商品删除与否并不重要
        omsCartMapper.deleteCartByUserIdAndSkuId(omsCart);
    }

    // 修改购物车商品数量
    @Override
    public void updateQuantity(CartUpdateDTO cartUpdateDTO) {
        // 要执行的业务是购物车数量的修改,需要的参数类型是OmsCart
        OmsCart omsCart=new OmsCart();
        // cartUpdateDTO只包含id和quantity,但是满足了修改购物车商品数量的条件
        BeanUtils.copyProperties(cartUpdateDTO,omsCart);
        // 执行修改
        omsCartMapper.updateQuantityById(omsCart);
    }

    // 前端将JWT发送给后端,后端在控制器方法运行前先运行过滤器
    // 过滤器中将JWT解析获取用户信息,然后已经将用户信息保存在SpringSecurity上下文中
    // 下面的方法将从SpringSecurity上下文中获取用户信息
    public SjmallAuthenticationInfo getUserInfo(){
        // 获取SpringSecurity上下文对象
        UsernamePasswordAuthenticationToken token=
                (UsernamePasswordAuthenticationToken)
                        SecurityContextHolder.getContext().getAuthentication();
        // 为了程序逻辑严谨,判断一下token是否为null
        if(token == null){
            throw new ShengJiServiceException(
                    ResponseCode.UNAUTHORIZED,"您还没有登录");
        }
        // 从SpringSecurity上下文对象中获取用户信息
        SjmallAuthenticationInfo userInfo=
                (SjmallAuthenticationInfo) token.getCredentials();
        // 最终返回用户信息
        return userInfo;
    }
    // 业务逻辑层使用用户信息,实际上只需要用id
    // 为了方法方法中获取用户id,这里编写一个方法
    public Long getUserId(){
        return getUserInfo().getId();
    }

}
